package com.lecture.java8.multithreading;

/**
 * @author luyn
 * @version 1.0
 * @description 创建三个窗口卖票
 * 1：问题：卖票过程中，出现了重票、错票-->出现了线程安全问题
 * 2：问题出现的原因：当某个线程操作票的过程中，尚未操作完成时，其他线程也参与进来，也操作车票
 * 3：如何解决：当一个线程a在操作ticket时，其他线程不能参与进来，直到线程a操作完成ticket时，其他线程才可以操作ticket，这种情况即使A线程出现了阻塞，也不能改变
 * 4：在Java中通过同步机制解决线程安全问题
 *
 * 方式一：同步代码块 synchronized(){
 *      //需要被同步的代码块
 * }
 * 1：操作共享数据的代码即为代码块。
 * 2：共享数据，多个线程共享操作的变量，比如ticket
 * 3：同步监视器，俗称锁，任何一个类的对象都可以充当锁
 *   要求：多个线程必须公用一把锁
 *   补充：在实现“runnable”接口创建多线程时，我们可以考虑使用this充当同步监视器。
 *
 *
 * 方式二：同步方法
 * 如果操作共享数据的代码完整的声明在一个方法中，我们可以把方法声明为同步的
 *
 *
 *
 *
 * 4：同步方式解决了线程安全问题。操作同步代码时只能有一个线程参与，其他线程等待。相当于是单线程，效率低。
 * @date 2021/1/13 20:36
 */
public class WindowTest1 {

    public static void main(String[] args) {
        Window1 w1 = new Window1();
        new Thread(w1).start();
        new Thread(w1).start();
        new Thread(w1).start();
    }
}

class Window1 implements Runnable{
    private  int  ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {

        while (true) {
            synchronized (obj){
                if (ticket > 0) {
                    /*try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }*/
                    System.out.println(Thread.currentThread().getName() + "：卖票，票号：" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}